/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "屏幕.h"

#include <场景/intern/S_Scene.h>

#include "框架/工作区/节点视口/ui节点视口.h"
#include "工作区/播放条.h"

#include "工作区/大纲/大纲工作区.h"
#include "工作区/库视口/库视口工作区.h"
#include "工作区/3D工作区/3D视口工作区.h"
#include "工作区/2D视口/2D视口工作区.h"
#include "工作区/文本视口/ui文本页面.h"
#include "工作区/节点视口/节点视口工作区.h"

#include "工作区/表格视口/表格工作区.h"

#include "工作区/时间轴视口/曲线视口工作区.h"
#include "工作区/时间轴视口/时间轴视口工作区.h"
#include "工作区/渲染器视口/渲染器视口工作区.h"
#include "工作区/视频图像视口/视频图像工作区.h"
#include "工作区/终端视口/终端工作区.h"


#include "框架/工作区/节点视口/节点操作.h"
#include "工作区/工作区弹出菜单.h"


#include "设置窗口/设置视口工作区.h"
#include "照壁界面/照壁主界面.h"


#include "物体编辑/物体编辑.h"
#include "物体管理/渲染物体约束更新.h"

#include "异步解算/物理异步解算.h"

#include "框架/菜单管理.h"


#include <core/时间.h>


static C_Widget* g页面添加菜单 = nullptr;
static C_Widget* g当前多页面 = nullptr;
//static C_Widget管理* gm

static float64 gdur;
static clock_t g时间start = clock();
static clock_t g时间end;





static bool f_平面页面标签结束拖动(C_Widget* self, C_Widget* 拾取的部件, S_拖放数据& data) {
	switch (data.m_Type) {
		case E_自定义拖放数据类型::e_拖放_节点子集按钮 : {
			//std::cout << "拾取的部件:" << data.m_Type << std::endl;
			C_工作区页面* 工作区 = f_屏幕_create工作区页面(*(self->m_UIctx), E_工作区类型::e_材质节点视口);
			if (工作区) {
				f_屏幕_添加工作区页面(self, 工作区, true);
				f_曲线视口工作区_设置当前编辑节点();
			}

			break;
		}
		default:
			break;
	}
	return true;
}


//C_Widget* on_Widget添加回调(C_Widget* r, uint32 当前同级组件数量) {
//	return nullptr;
//}
static E_事件是否传递 on_Widget添加回调(C_Widget* self, const E_鼠标按钮& 按钮) {
	g当前多页面 = self->m_父部件;

	f_ui_打开弹出窗口(g页面添加菜单, self->m_GlobalLoc);
	return E_事件是否传递::e_事件传递_终止;
}





C_工作区页面* f_屏幕_create工作区页面(S_UI渲染环境& ctx, E_工作区类型 type, E_方向 方向) {
	C_工作区页面* 工作区 = nullptr;

	switch (type) {
		case e_库: {
			工作区 = f_工作区_创建库视口(ctx);
			工作区->m_WName = u"库";
			break;
		}

		case e_3D视口: {
			工作区 = f_工作区_创建3D视口(ctx);
			工作区->m_WName = u"3D视口";
			break;
		}

		case E_工作区类型::e_曲线视口: {
			工作区 = f_工作区_创建曲线视口(ctx);
			工作区->m_WName = u"曲线视口";
			break;
		}

		case e_视频图像: {
			工作区 = f_工作区_创建视频图像(ctx);
			工作区->m_WName = u"视频图像";
			break;
		}

		case e_时间轴: {
			工作区 = f_工作区_创建时间轴视口(ctx);
			工作区->m_WName = u"时间轴";
			break;
		}

		case e_节点视口: {
			工作区 = f_工作区_创建节点视口(ctx);
			工作区->m_WName = u"节点1";
			break;
		}

		case e_材质节点视口: {
			//工作区 = f_工作区_create材质节点视口(ctx);
			工作区 = f_工作区_创建节点视口(ctx);
			工作区->m_WName = u"材质1";
			break;
		}

		case e_渲染合成视口: {
			工作区 = f_工作区_创建渲染器视口(ctx);
			工作区->m_WName = u"渲染合成";
			break;
		}

		case E_工作区类型::e_2D视口: {
			工作区 = f_工作区_创建2D视口(ctx);
			工作区->m_WName = u"2D视口";
			break;
		}

		case E_工作区类型::e_表格视口: {
			工作区 = f_工作区_创建表格视口(ctx);
			工作区->m_WName = u"表格";
			break;
		}

		case E_工作区类型::e_文本编辑视口: {
			工作区 = f_工作区_创建文本编辑视口(ctx);
			工作区->m_WName = u"文本编辑";
			break;
		}

		case E_工作区类型::e_设置视口: {
			工作区 = f_工作区_创建设置视口(ctx);
			工作区->m_WName = u"设置";
			break;
		}

		case E_工作区类型::e_大纲视口: {
			工作区 = f_工作区_创建大纲视图(ctx);
			工作区->m_WName = u"大纲";
			break;
		}

		case E_工作区类型::e_模块视口: {
			工作区 = f_工作区_create堆栈节点视口(ctx);
			工作区->m_WName = u"堆栈节点";
			break;
		}

		case E_工作区类型::e_终端视口: {
			工作区 = f_工作区_创建终端视图(ctx);
			工作区->m_WName = u"终端视口";
			break;
		}
		default:
			break;
	}

	工作区->m_是否延展 = { true, true };
	return 工作区;
}


static void on_窗口根布局布局(C_Widget* r, C_Widget** w, uint32 num) {
	if(!num) return;
	float32 dpi = r->m_UIctx->m_DPI;

	vec2 pos = {};
	vec2 size = r->m_Size;
	w[0]->f_setPos(pos);
	pos.y = 24 * dpi;
	w[0]->f_setSize({size.x, pos.y});
	size.y -= pos.y;

	if(num < 2) return;
	f_VBOX布局(pos, size, &w[1], num - 1);
	
}

void f_屏幕_创建窗口根布局(S_Window* window, bool 创建菜单) {
	C_Widget* w = new C_Widget();
	w->m_TypeName = DEF_WIDGET_根布局;
	w->mf_布局 = on_窗口根布局布局;
	w->m_区域帧缓存根 = w;
	f_window_安装UI(window, w);
	S_框架::m_全局底层渲染层ID分配.f_置组件渲染层(w);

	auto ui主菜单 = f_界面构建_主菜单创建(*f_window_getUI环境(window));
	w->f_添加子组件(ui主菜单);

}






static std::map<std::u16string, E_工作区类型> g工作区类型名称;



static bool on_菜单项点击(C_Widget* self, const std::u16string name, uint16 id) {
	C_工作区页面* 工作区 = nullptr;

	if (g工作区类型名称.find(name) != g工作区类型名称.end()) {
		E_工作区类型 type = g工作区类型名称[name];

		工作区 = f_屏幕_create工作区页面(*(g当前多页面->m_UIctx), type);
		if (工作区) {
			f_屏幕_添加工作区页面(g当前多页面, 工作区, true);
			//f_曲线视口工作区_设置当前编辑节点();
		}
	}

	return false;
}





void f_屏幕_初始化工作区(S_UI渲染环境& ctx) {
	
	g工作区类型名称[DEF_3D视口工作区] = E_工作区类型::e_3D视口;
	g工作区类型名称[DEF_库视口工作区] = E_工作区类型::e_库;
	//g工作区类型名称[DEF_节点视口工作区] = E_工作区类型::e_节点视口;
	g工作区类型名称[DEF_曲线视口工作区] = E_工作区类型::e_曲线视口;
	g工作区类型名称[DEF_时间视口工作区] = E_工作区类型::e_时间轴;
	g工作区类型名称[DEF_材质视口工作区] = E_工作区类型::e_材质节点视口;
	g工作区类型名称[DEF_2D视口工作区]   = E_工作区类型::e_2D视口;
	//g工作区类型名称[DEF_非编视口工作区] = E_工作区类型::e_非编视口;
	g工作区类型名称[DEF_渲染视口工作区] = E_工作区类型::e_渲染合成视口;
	g工作区类型名称[DEF_表格视口工作区] = E_工作区类型::e_表格视口;
	g工作区类型名称[DEF_设置视口工作区] = E_工作区类型::e_设置视口;
	g工作区类型名称[DEF_视频图像工作区] = E_工作区类型::e_视频图像;
	g工作区类型名称[DEF_大纲视图工作区] = E_工作区类型::e_大纲视口;
	g工作区类型名称[DEF_终端视图工作区] = E_工作区类型::e_终端视口;

	
	S_键盘键位映射 快捷键 = {};
	快捷键.event = f_工作区_全局播放时间帧;
	快捷键.键盘按键[0] = S_InputKey::e_KEY_左ALT;
	快捷键.键盘按键[3] = S_InputKey::e_KEY_A;
	快捷键.键盘状态[0] = DEF_按键状态_按下中 | DEF_按键状态_放开;
	快捷键.键盘状态[3] = DEF_按键状态_放开;
	f_ui_注册全局快捷键(快捷键);

	
	f_工作区页面_3D视口界面初始化(ctx);
	f_工作区页面_物体节点工作区初始化(ctx);
	f_工作区页面_库工作区初始化(ctx);
	f_工作区页面_曲线视口初始化(ctx);
	f_工作区页面_设置视口初始化(ctx);
	f_工作区页面_视频图像初始化(ctx);
	f_工作区页面_大纲视图初始化(ctx);

	if (ctx.m_Ctx.m_支持光追) {
		f_工作区页面_渲染合成节点工作区初始化(ctx);
	}
	else {

	}


	S_菜单创建参数 参数 = {
		on_菜单项点击,
		{
			{DEF_3D视口工作区,		u"透视",			u""},
			//{DEF_库视口工作区,		u"image_text",		u""},
			//{DEF_节点视口工作区,	u"二叉树",			u""},
			{DEF_曲线视口工作区,	u"曲线顶点"},
			{DEF_时间视口工作区,	u"playback_reload",	u""},
			//{DEF_材质视口工作区,	u"05_关照多维材质"},
			{DEF_2D视口工作区,      u"font-451",		u""},

			//{DEF_非编视口工作区,	"indent_increase"},
			//{DEF_渲染视口工作区,	u"layers_1"},
			//{DEF_表格视口工作区,	u"分割"},
			//{DEF_视频图像工作区,	u"图像"},
			//{DEF_UI构建视口工作区,	u"app_window_black"},

			{DEF_大纲视图工作区,    u"树",				u""},
			{DEF_终端视图工作区,    u"终端",			u""},
		}
	};
	g页面添加菜单 = f_ui_创建菜单(ctx, E_方向::e_纵向, 参数);
}

void f_屏幕_清理工作区() {
	f_node_销毁操作数据();
}

//void f_屏幕_开始更新工作区() {
//	//更新控制柄
//	vec3 pos = f_global_get激活物体包围中心点();
//	//S_框架::g_变换手柄->f_set位置(pos);
//	//f_camera_get眼睛位置()
//}


bool f_工作区_时间步进() {
	f_scene_设置光追渲染器视口渲染(f_NodeCtx_get默认场景(), false);

	if (f_NodeCtx_更新()) {
		auto& frame = f_NodeCtx_get帧();
		int32 当前帧 = frame.当前帧;
		auto 区间 = frame.帧区间;


		if (S_光追后端::g_渲染状态 == E_离线渲染状态::e_光追渲染_关) {
			if (S_框架::g_播放帧) {
				int32 方向 = 1;
				//std::cout << "方向 = " << 方向 << std::endl;
				g时间end = clock();
				gdur = (double)(g时间end - g时间start);
				gdur = (gdur * 1000 / CLOCKS_PER_SEC);

				if (gdur >= 16.666) {
					g时间start = clock();
				}
				else {
					f_NodeCtx_更新完成();
					return false;
				}

				f_时间工作区_帧步进(1);
				f_时间轴页面_联动更新();
				f_曲线视口页面_联动更新();

				if (当前帧 >= frame.帧区间.y) {
					f_NodeCtx_set当前帧(frame.帧区间.x);
					f_ob_set步进时间帧(frame.帧区间.x);
				}
				else {
					f_NodeCtx_start模拟步数();
				}
				//frame.当前帧.m_UI->m_Set(frame.当前帧);
				f_node_Step节点树();

			}
			else {

				f_node_Step节点树();

				f_工作区_联动更新(E_工作区类型::e_时间轴, E_工作区操作类型::e_所有);
			}

			f_scene_设置光追渲染器视口渲染(f_NodeCtx_get默认场景(), true);
		}

		f_NodeCtx_更新完成();
		return false;
	}
	return true;
}


C_Widget* f_屏幕_创建工作区(S_UI渲染环境& ctx, E_方向 方向) {
	std::vector<C_Widget*> ws;
	auto* 多页面窗口 = f_ui_创建多页面(ctx, 方向, ws);
	多页面窗口->m_TypeName = "工作区";
	多页面窗口->m_WName = u"工作区多页面";
	多页面窗口->mf_结束拖拽 = f_平面页面标签结束拖动;
	多页面窗口->m_是否延展 = { true, true };

	if (方向 == E_方向::e_横向) {
		f_ui_设置多页面头(多页面窗口, { 80, 20 });
	}
	else {
		f_ui_设置多页面头(多页面窗口, { 20, 20 });
	}
	f_ui_set多页面添加事件(多页面窗口, on_Widget添加回调, { 20,20 });
	
	

	S_框架::m_工作区视口渲染层ID分配.f_置组件渲染层(多页面窗口);
	return 多页面窗口;
}

void f_屏幕_添加工作区页面(C_Widget* 屏幕, C_Widget* page, bool 设置为当前页面) {
	uint32 id = f_ui_多页面添加页面(屏幕, page);
	
	if (设置为当前页面) {
		f_ui_set多页面当前页面(屏幕, id);
	}
	
	屏幕->m_更新绘制属性 = true;
}






bool f_屏幕_更新工作区() {
	//f_表格视口页面_联动更新();
	//f_NodeCtx_更新(true);

	switch (S_光追后端::g_渲染状态) {
		case E_离线渲染状态::e_光追渲染_单帧:
		case E_离线渲染状态::e_光追渲染_序列: {
			break;
		}
		default: {
			f_物体约束_更新场景物体();


			//if (S_框架::g_标记变换更新后事件 >= 0) {
			//	//f_camera_set偏移视点(camera, f_global_get激活物体中心点());
			//	--S_框架::g_标记变换更新后事件;
			//
			//}
			
			//f_NodeView_更新节点结构();

			//if (f_工作区_时间步进() == false) {
			//	f_NodeCtx_get默认场景()->f_Update(nullptr);
			//
			//	f_global_update编辑对象();
			//	f_NodeOps_更新独立显示节点();
			//	f_NodeCtx_执行模拟计算();
			//}
			//f_node_执行约束计数();

			break;
		}
	}

	//if (f_node_销毁物体()) {
	//	f_NodeCtx_clear选中物体();
	//}

	//f_NodeCtx_更新完成();
	return false;
}





